# coding: utf-8
from ctypes import *
import re
import atexit
import json
import platform
from concurrent.futures import ThreadPoolExecutor, wait, ALL_COMPLETED
import os
import subprocess

def find_vs_with_vswhere():
    try:
        result = subprocess.run(
            ["./windows64/vswhere.exe", "-latest", "-products", "*", "-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "-property", "installationPath"],
            capture_output=True, text=True
        )
        if result.returncode == 0:
            vs_path = result.stdout.strip()
            vcvars_path = os.path.join(vs_path, "VC", "Auxiliary", "Build", "vcvars64.bat")
            return vcvars_path
    except Exception as e:
        print(f"vswhere 执行失败: {e}")
    return None

def check_dll_with_dumpbin(dll_path):
    try:
        vs_path = find_vs_with_vswhere()
        full_cmd = f'"{vs_path}" && dumpbin /DEPENDENTS {dll_path}'
        result = subprocess.run(full_cmd, shell=True, capture_output=True, text=True)
        if result.returncode == 0:
            print(result.stdout)
        else:
            print(result.stderr)
    except FileNotFoundError:
        print("请安装 Visual Studio 并确保 dumpbin 在 PATH 中。")

def check_dll_dependencies(dll_path):
    try:
        lib = WinDLL(dll_path)
        print(f"[成功] {dll_path} 加载成功，依赖完整。")
        return True
    except OSError as e:
        print(f"[失败] {dll_path} 加载失败，可能缺少依赖: {e.winerror}")
        print(f"错误信息: {e}")
        check_dll_with_dumpbin(dll_path)
        return False
# 默认开启内存检查，如果asan的dll依赖不一致，手工从VS目录中拷贝此文件替换。    
check_dll_dependencies("./windows64/clang_rt.asan_dynamic-x86_64.dll")
check_dll_dependencies("./function/cbs_tools.dll")

DBTYPE = "gauss-v1"
system = platform.system()
config = open("./conf/frame-win-v3-rzrq.xml", "r", encoding="utf-8")
config_str = ""
for line in config.readlines():
    if system == "Linux" and "program" in line and "dll" in line:
        line = line.replace('path="', 'path="lib')
        line = line.replace('dll', 'so')
    elif system == "Windows" and "program" in line and "so" in line:
        line = line.replace('path="lib', 'path="')
        line = line.replace('so', 'dll')
    config_str = config_str + line
print(config_str)

frame = CDLL("./windows64/kcps_frame.dll" if system ==
                                             "Windows" else "./arm/libkcps_frame.so")

KcpsFrameInit = getattr(frame, "KcpsFrameInit")
KcpsFrameExecute = getattr(frame, "KcpsFrameExecute")
KcpsFrameExecute.argtypes = (
    c_int, c_char_p, c_int, POINTER(c_char_p), POINTER(c_int))
KcpsFrameExit = getattr(frame, "KcpsFrameExit")


def test(param, worker=0):
    param_bytes = bytes(json.dumps(param), "utf-8")
    res = c_char_p()
    res_size = c_int()
    try:
        KcpsFrameExecute(worker, param_bytes, len(param_bytes),
                         byref(res), byref(res_size))
    except ValueError as e:
        print(f"ValueError: {e}")
    except OSError as e:
        print(f"OSError: {e}")
    except Exception as e:
        print(f"An unexpected error occurred: {e}")
    if res.value:
        print(res.value.decode('utf-8'))
    else:
        print("结果为空")


def init():
    # 设置环境变量
    if system != 'Linux':
        print(os.getenv("PATH"))
        PATH =f'{os.getcwd()}\\windows64;{os.getcwd()}\\function;'
        if PATH not in str(os.getenv('PATH')):
            os.environ['PATH'] = PATH + str(os.getenv('PATH'))
        print(os.getenv('PATH'))
    else:
        print(os.getenv("LD_LIBRARY_PATH"))
        PATH =f'{os.getcwd()}/arm;{os.getcwd()}/function;'
        if PATH not in str(os.getenv('LD_LIBRARY_PATH')):
            os.environ['LD_LIBRARY_PATH'] = PATH + str(os.getenv('LD_LIBRARY_PATH'))
        print(os.getenv('LD_LIBRARY_PATH'))

    # 构造dbinfo
    init_param1 = json.load(open("./init_param.json", "r", encoding="utf-8"))[DBTYPE]
    init_param1["func_id"] = 0
    init_param1["driver"] = init_param1["driver"]["linux" if system == "Linux" else "windows"] if DBTYPE != "oceanbase-oracle" else ""

    pattern = r'([\d|\.]+):(\d*)/(\w*)'
    urls=re.findall(pattern, init_param1["serverip"])
    init_param1["server"]=urls[0][0]
    init_param1["port"]=urls[0][1]
    init_param1["database"]=urls[0][2]

    dbinfo = "instname=comm|driver={}|server={}|port={}|database={}|username={}|password={}|odbc_ext={}".format(
            init_param1["driver"], init_param1["server"], init_param1["port"], init_param1["database"]
              , init_param1["userid"], init_param1["userpassword"], init_param1["odbc_ext_connect_str"])

    if KcpsFrameInit(bytes(config_str, "utf-8"), bytes(dbinfo, "utf-8")) != 0:
        raise ValueError("初始化失败")

    init_macbs()

def init_macbs():
    init_param = json.load(open("./init_param.json", "r", encoding="utf-8"))[DBTYPE]
    init_param["func_id"] = 0
    init_param["driver"] = init_param["driver"]["linux" if system == "Linux" else "windows"] if DBTYPE != "oceanbase-oracle" else ""
    init_param = bytes(json.dumps(init_param), "utf-8")
    res = c_char_p()
    res_size = c_int()
    KcpsFrameExecute(0, init_param, len(init_param),
                     byref(res), byref(res_size))
    print(res.value.decode("utf-8") if res.value else "结果为空")


@atexit.register
def exit():
    KcpsFrameExit()
    print("exit")


if __name__ == "__main__":
    print(os.getpid())
    init()

    # test_shjsmx()
    # simulate()

    # test
    while True:
        # 打印测试用例
        cases = json.load(open("./case-new-v3.json", "r", encoding="utf-8"))
        print("测试用例列表:")
        for i in range(len(cases)):
            case = cases[i]
            if "NAME" in case:
                print(i, ":", case["NAME"])
            else:
                raise ValueError("存在用例未找到NAME属性" + json.dumps(case))

        # 等待测试用例id输入
        case_id = input("\ninput test case index:")
        if case_id == "exit":
            break
        elif not case_id or int(case_id) > len(cases) - 1:
            print("未找到测试用例")
            continue
        else:
            test(cases[int(case_id)])



szkingdom.py
